import os
from abc import ABC, abstractmethod, abstractproperty
import subprocess as sp


class AbstractServerObject(ABC):
    def __init__(self): ...

    @abstractmethod
    def start(self): ...

    @abstractmethod
    def exit(self): ...


class SingleServerObject(AbstractServerObject):
    def __init__(self, executor: str = "java", path: str = "", file: str = "server.jar", options: list[str] = ()):
        super().__init__()
        self.executor = executor
        self.server = None
        self.path = path
        self.file = file
        self.options = options
        self.args = ()

    def start(self):
        target = self.path + os.sep + self.file
        self.args = (self.executor + ' '.join(self.options) + target)
        self.server = sp.Popen(
            args=self.args,
            cwd=self.path,
            text=True,
            stdin=sp.PIPE,
            stdout=sp.PIPE,
            stderr=sp.PIPE,
            start_new_session=True,
            bufsize=1,
            universal_newlines=True,
        )

    def exit(self):
        if self.server is not None:
            self.server.stdin.close()
            self.server.terminate()

    def command(self, command: str):
        if self.server is not None:
            self.server.stdin.write(f"{command}\n")
            self.server.stdin.flush()


class AbstractConstructor(ABC):

    executor: str = ""
    args: list[str] = []

    @abstractmethod
    def __init__(self): ...

    @abstractmethod
    def construct(self, **kwargs) -> AbstractServerObject: ...
